package com.xianyu.us.common.aspect;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.xianyu.us.common.annotatian.ExtCacheable;
import com.xianyu.us.common.exception.ServiceException;
import com.xianyu.us.common.utils.RedisUtils;

/**
 * redis方法切面类
 * @author wangshili
 *
 */
@Aspect
@Component
public class RedisAspect {
	
	@Autowired
	private RedisUtils redisUtils;
	
	private Logger log = LoggerFactory.getLogger(getClass());
	    //是否开启redis缓存  true开启   false关闭
	    @Value("${spring.redis.open:false}") //读取配置文件的配置，默认是给false
	    private boolean open;
	    
	    @Around("bean(redisUtils)")
	    public Object aroundUtils(ProceedingJoinPoint point) throws Throwable {
	        Object result = null;
	        if(open){ //如果为true就执行方法,不存在就报异常
	            try{
	                result = point.proceed();
	            }catch (Exception e){
	            	log.error("redis error");
	                throw new ServiceException("redis服务异常");
	            }
	        }
	        return result;
	    }
	    
	    /**
	     * 对ExtCacheable注解切面
	     * @param jc
	     * @return
	     * @throws Throwable 
	     */
	    @Around("@annotation(com.xianyu.us.common.annotatian.ExtCacheable)")
	    public Object aroundAnnotation(ProceedingJoinPoint jc) throws Throwable {
	    	//1.获取signature签名
	 		MethodSignature ms = 
	 				(MethodSignature)jc.getSignature();
	 		Method method = ms.getMethod();
	 		//获取请求的参数
			Object[] args = jc.getArgs();
			String params = Arrays.toString(args);	
	 		//获取注解
	 		ExtCacheable annotation = method.getAnnotation(ExtCacheable.class);
	    	String key=annotation.key(); //获取key
	    	String value=annotation.value(); //获取值
	    	int expireTime=annotation.expireTime();//获取保存时间
	    	
	    	if(key.equals("")) { //如果key为空，默认使用输入参数组合作为key
	    		key=params;
	    	}
	    	//如果是验证码，则需要先删除原有的数据再缓存新的验证码
	    	if(value.equals("VerificationCode")) {
	    		redisUtils.del(value);
	    	}
	    	//如果缓存中已存在该数据，则直接返回
	    	if(redisUtils.hHasKey(value, key)) {
	    		return redisUtils.hget(value, key);
	    	}
	    	
	    	//执行函数
	    	Object result = jc.proceed();
	    	
	    	Map<String, Object> map = new HashMap<String,Object>();
	    	map.put(key, result);
	    	redisUtils.hmset(value, map, expireTime);
	 		return result;
	    }
}
